///\file mt_convolution.cpp
///\brief contient les implémentations de la classe MThread::Convolution
///\author { V.Allombert, A.Blanchard, A.Carteron, V.Pelletier } 
#include "mt_convolution.hh"
#include <pthread.h>

#include <iostream>

namespace MThread{
  void* Convolution::sconvol(void *v)
  {
    convargs* a = (convargs*) v;

    for(unsigned int i = a->start; i < a->end; i++)
      for(unsigned int j = a->c->m.width()/2; 
	  j < a->image->width()-a->c->m.width()/2; 
	  j++)
	a->c->calc((*(a->result))[i][j], *(a->image), i, j);

    return 0;
  }

  Convolution::Convolution(const Matrix<int> &m, unsigned int d): Generic::Convolution(m,d){}

  void Convolution::convol(const Image& image, Image &result) const{
    convargs a[CORES];
    for(unsigned int i = 0; i < CORES; i++){
      a[i].c = this;
      a[i].image = &image;
      a[i].result = &result;
      a[i].start = i*(    image.height()/CORES);
      a[i].end   = (i+1)*(image.height()/CORES);
    }
    
    a[0].start = m.height();
    a[CORES-1].end   = image.height() - m.height();

    pthread_t t[CORES-1];
    for(unsigned int i = 0; i < CORES-1; i++)
      pthread_create(&t[i], NULL, sconvol, (void*) &a[i]);
    sconvol(&a[CORES-1]);

    for(unsigned int i = 0; i < CORES-1; i++)
      pthread_join(t[i], NULL);
  }

  void Convolution::calc(pixel &p, const Image &image, 
			 unsigned int y, unsigned int x) const
  {
    float r = 0;
    float g = 0;
    float b = 0;
    float a = 0;
    x -= m.width()/2;
    y -= m.height()/2;
    for(unsigned int i = 0; i < m.height(); i++)
      for(unsigned int k = 0; k < m.width(); k++){
	r += image[y+i][x+k].r*m[i][k];
	g += image[y+i][x+k].g*m[i][k];
	b += image[y+i][x+k].b*m[i][k];
	a += image[y+i][x+k].a*m[i][k];
      }

    p.r = (r > 0)*(r/divider);
    p.g = (g > 0)*(g/divider);
    p.b = (b > 0)*(b/divider);
    p.a = (a > 0)*(a/divider);
  }
}
